/**
 * Copyright (c) 2019-2030 panguBpm All rights reserved.
 * <p>
 * http://www.pangubpm.com/
 * <p>
 * （盘古BPM工作流平台）
 */
package com.pangubpm.bpm.dmn.feel.impl.juel.transform;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.pangubpm.bpm.dmn.feel.impl.juel.FeelEngineLogger;
import com.pangubpm.bpm.dmn.feel.impl.juel.FeelLogger;

public class ListTransformer implements FeelToJuelTransformer {

  public static final FeelEngineLogger LOG = FeelLogger.ENGINE_LOGGER;
  // regex to split by comma which does a positive look ahead to ignore commas enclosed in quotes
  public static final String COMMA_SEPARATOR_REGEX = ",(?=([^\"]*\"[^\"]*\")*[^\"]*$)";

  public boolean canTransform(String feelExpression) {
    return splitExpression(feelExpression).size() > 1;
  }

  public String transform(FeelToJuelTransform transform, String feelExpression, String inputName) {
    List<String> juelExpressions = transformExpressions(transform, feelExpression, inputName);
    return joinExpressions(juelExpressions);
  }

  protected List<String> collectExpressions(String feelExpression) {
    return splitExpression(feelExpression);
  }

  private List<String> splitExpression(String feelExpression) {
    return Arrays.asList(feelExpression.split(COMMA_SEPARATOR_REGEX, -1));
  }

  protected List<String> transformExpressions(FeelToJuelTransform transform, String feelExpression, String inputName) {
    List<String> expressions = collectExpressions(feelExpression);
    List<String> juelExpressions = new ArrayList<String>();
    for (String expression : expressions) {
      if (!expression.trim().isEmpty()) {
        String juelExpression = transform.transformSimplePositiveUnaryTest(expression, inputName);
        juelExpressions.add(juelExpression);
      }
      else {
        throw LOG.invalidListExpression(feelExpression);
      }
    }
    return juelExpressions;
  }

  protected String joinExpressions(List<String> juelExpressions) {
    StringBuilder builder = new StringBuilder();
    builder.append("(").append(juelExpressions.get(0)).append(")");
    for (int i = 1; i < juelExpressions.size(); i++) {
      builder.append(" || (").append(juelExpressions.get(i)).append(")");
    }
    return builder.toString();
  }

}
